package com.nbicc.survey.service.impl;

import com.github.pagehelper.Page;
import com.nbicc.common.Const;
import com.nbicc.common.RequestPageObj;
import com.nbicc.common.ResponseObj;
import com.nbicc.parent.serivce.BaseService;
import com.nbicc.spring.CurrentRequestUtils;
import com.nbicc.survey.mapper.AnswerMapper;
import com.nbicc.survey.po.*;
import com.nbicc.survey.service.IAnswerService;
import com.nbicc.survey.service.IQuestionnaireService;
import com.nbicc.survey.service.ITopicService;
import com.nbicc.utils.ToolUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("AnswerServiceImpl")
public class AnswerServiceImpl extends BaseService implements IAnswerService {

    @Autowired
    private AnswerMapper answerMapper;
    @Resource(name = "TopicServiceImpl")
    private ITopicService topicService;
    @Resource(name = "QuestionnaireServiceImpl")
    private IQuestionnaireService questionnaireService;

    @Override
    public Answer selectById(String id) {
        return answerMapper.selectById(id);
    }

    @Transactional
    @Override
    public Integer insert(Answer answer){

        checkAnswer(answer);

        answer.setId(ToolUtil.generateUUID32());
        answer.setRespondentId(CurrentRequestUtils.getRemoteAddr());
        answer.setCreateTime(new Date());
        return answerMapper.insert(answer);
    }

    /**
     * 校验答案
     * @param answer
     */
    private void checkAnswer(Answer answer){

        if(!questionnaireService.allowToAnswer(answer.getQuestionnaireId())){
            throw new RuntimeException("此问卷已不允许答题");
        }

        Topic topic = topicService.selectById(answer.getTopicId());
        if(topic == null){
            throw new RuntimeException("无效问题");
        }

        switch (topic.getTopicType()){
            case MultipleChoice:
                checkMultipleChoiceTopicAnswer(topic,answer);
                break;
            case MultipleSelection:
                checkMultipleSelectionTopicAnswer(topic,answer);
                break;
            case EssayQuestion:
                break;
             default:
                    break;
        }

    }

    private void checkMultipleChoiceTopicAnswer(Topic topic,Answer answer){
        if(topic instanceof MultipleChoiceTopic){
            MultipleChoiceTopic multipleChoiceTopic = (MultipleChoiceTopic) topic;
            if(!multipleChoiceTopic.getOptionListStr().contains(answer.getResult())){
                throw new RuntimeException("非法答案:"+answer.getResult() + "不在"+multipleChoiceTopic.getOptionListStr());
            }
            if(alreadyAnswer(answer.getQuestionnaireId(),answer.getTopicId(),CurrentRequestUtils.getRemoteAddr(),null)){
                throw new RuntimeException("不要重复回答问题");
            }
        }
    }

    private void checkMultipleSelectionTopicAnswer(Topic topic,Answer answer){
        if(topic instanceof MultipleSelectionTopic){
            MultipleSelectionTopic multipleSelectionTopic = (MultipleSelectionTopic) topic;
            if(!multipleSelectionTopic.getOptionListStr().contains(answer.getResult())){
                throw new RuntimeException("非法答案:"+answer.getResult() + "不在"+multipleSelectionTopic.getOptionListStr());
            }
            if(alreadyAnswer(answer.getQuestionnaireId(),answer.getTopicId(),CurrentRequestUtils.getRemoteAddr(),answer.getResult())){
                //多选题 允许提交多个答案 但是答案不允许重复
                throw new RuntimeException("不要重复回答问题");
            }
        }
    }

    public int countByRespondentIdAndTopicIdOrResult(String questionnaireId, String topicId , String respondentId,String result){
        return answerMapper.countByRespondentIdAndTopicIdOrResult(questionnaireId,topicId ,respondentId,result);
    }

    /**
     * 用户是否回答过这个问题
     * @param questionnaireId
     * @param topicId
     * @param respondentId      （ip）
     * @param result
     * @return
     */
    public boolean alreadyAnswer(String questionnaireId, String topicId , String respondentId,String result){
        return countByRespondentIdAndTopicIdOrResult(questionnaireId,topicId ,respondentId,result) > 0;
    }

    @Transactional
    @Override
    public Integer batchInsert(List<Answer> answerList) throws Exception {
        for (Answer answer : answerList) {
            this.insert(answer);
        }
        return 1;
    }

    @Override
    public Integer updateById(Answer answer) {
        return answerMapper.updateById(answer);
    }

    @Override
    public Integer deleteById(String id) {
        return answerMapper.deleteById(id);
    }

    /**
     * @param questionnaireId   问卷id
     * @param topicId           题目id
     * @return
     */
    @Override
    public Integer countAnswererByQuestionnaireIdAndTopicId(String questionnaireId, String topicId) {
        return answerMapper.countAnswererByQuestionnaireIdAndTopicId(questionnaireId,topicId);
    }

    @Override
    public List<Map<String, Serializable>> resultAggregator(String questionnaireId, String topicId) {
        Topic topic = topicService.selectById(topicId);
        if(topic == null || (topic.getTopicType() != TopicTypeEnum.MultipleChoice && topic.getTopicType() != TopicTypeEnum.MultipleSelection) ){
            //只有选择题才能做聚合操作
            throw new RuntimeException("无效topicId");
        }
        return answerMapper.resultAggregator(questionnaireId,topicId);
    }

    @Override
    public ResponseObj find(RequestPageObj<Map<String, Object>> requestPageObj) {
        setPageHelper(requestPageObj , Answer.TABLE_SURVEY_ANSWER);
        List<Answer> answerList = answerMapper.selectByMap(requestPageObj.getData());
        return new ResponseObj(Const.HTTP_STATUS_SUCCESS, answerList, ((Page<?>) answerList).getTotal());
    }

    @Override
    public QuestionnaireTopicEntire statisticsQuestionnaire(String questionnaireId) {
        QuestionnaireTopicEntire questionnaireTopicEntire = questionnaireService.selectByIdEntire(questionnaireId);
        questionnaireTopicEntire.setMultipleChoiceTopicList(multipleChoiceTopicList2MultipleChoiceTopicWithStatisticsList(questionnaireId,questionnaireTopicEntire.getMultipleChoiceTopicList()));
        questionnaireTopicEntire.setMultipleSelectionTopicList(multipleSelectionTopicList2MultipleSelectionTopicWithStatisticsList(questionnaireId,questionnaireTopicEntire.getMultipleSelectionTopicList()));
        return questionnaireTopicEntire;
    }

    private List<MultipleChoiceTopic> multipleChoiceTopicList2MultipleChoiceTopicWithStatisticsList(String questionnaireId,List<MultipleChoiceTopic> multipleChoiceTopicList){
        List<MultipleChoiceTopic> multipleChoiceTopicWithStatisticsList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(multipleChoiceTopicList)){
            for (MultipleChoiceTopic multipleChoiceTopic : multipleChoiceTopicList) {
                MultipleChoiceTopicWithStatistics multipleChoiceTopicWithStatistics = new MultipleChoiceTopicWithStatistics();
                BeanUtils.copyProperties(multipleChoiceTopic,multipleChoiceTopicWithStatistics);
                multipleChoiceTopicWithStatistics.setAnswerersNumber(this.countAnswererByQuestionnaireIdAndTopicId(questionnaireId,multipleChoiceTopic.getId()));
                multipleChoiceTopicWithStatistics.setResultAggregator(this.resultAggregator(questionnaireId,multipleChoiceTopic.getId()));
                multipleChoiceTopicWithStatisticsList.add(multipleChoiceTopicWithStatistics);
            }
        }
        return multipleChoiceTopicWithStatisticsList;
    }

    private List<MultipleSelectionTopic> multipleSelectionTopicList2MultipleSelectionTopicWithStatisticsList(String questionnaireId,List<MultipleSelectionTopic> multipleSelectionTopicList){
        List<MultipleSelectionTopic> multipleSelectionTopicWithStatisticsList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(multipleSelectionTopicList)){
            for (MultipleSelectionTopic multipleSelectionTopic : multipleSelectionTopicList) {
                MultipleSelectionTopicWithStatistics multipleSelectionTopicWithStatistics = new MultipleSelectionTopicWithStatistics();
                BeanUtils.copyProperties(multipleSelectionTopic,multipleSelectionTopicWithStatistics);
                multipleSelectionTopicWithStatistics.setAnswerersNumber(this.countAnswererByQuestionnaireIdAndTopicId(questionnaireId,multipleSelectionTopic.getId()));
                multipleSelectionTopicWithStatistics.setResultAggregator(this.resultAggregator(questionnaireId,multipleSelectionTopic.getId()));
                multipleSelectionTopicWithStatisticsList.add(multipleSelectionTopicWithStatistics);
            }
        }
        return multipleSelectionTopicWithStatisticsList;
    }

}
